#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
#0123456789012345678901234567890123456789
# 12 4   8      16              32
# 
# c+4/2
# f-3/8.
# a=5/1

window.cde ?= {}

cde.TICKS_HOLE   = 96
cde.C0_MIDI      = 12
cde.SYMBOL_INDEX = 'c': 0, 'd': 2, 'e': 4, 'f': 5, 'g': 7, 'a': 9, 'b': 11

### ===========================================================
@sym = 'a'..'g'
@alt = '+'/'-' (sharp/bemol)
@oct = 0..9
###
class Note
	@PATTERN = ///
		([a-g]{1})	# note symbol
		([+-]?)			# alteration sign: '+' for sharp, '-' for bemol
		(\d{1})			# octave number
		///
	
	constructor: (@label) ->
		[@sym, alt, @oct] = @label.match( Sound.PATTERN)[1..3]
		@alt = switch alt
			when '+' then +1 
			when '-' then -1 
			else 0
				
		@idx = cde.SYMBOL_INDEX[@sym] + @alt
		@mid = cde.C0_MIDI + 12 * @oct + @idx
		
		console.log "NEW Note:sym:#{@sym}|alt:#{@alt}|oct:#{@oct}|idx:#{@idx}|mid:#{@mid}"

cde.Note = Note
				
### ===========================================================
@value  = 1,2,4,8,16,32
@mult	= '.'/'3' (dot or triplet)
@ticks  = ticks per note
###
class Dur
	@PATTERN = ///
		([1|2|4|8|G|W]{1})	# note value
		([\.|3]?)			# dot or triplet
		///
		
	constructor: (@desc) ->
		[value, mult] = @desc.match(Dur.PATTERN)[1..2]
		
		@value = switch value
			when 'G' then 16
			when 'W' then 32
			else value
				
		@mult  = switch mult 
			when '.' then 1.5 
			when '3' then 2/3
			else 1
				
		@time = cde.TICKS_HOLE / @value * @mult
		
		console.log "NEW Dur:val:#{@value}|mult:#{@mult}|time:#{@time}"


cde.Dur = Dur

### ===========================================================
# sound: note and duration
###
class Sound
	constructor: (@note, @dur) ->
	
	trace: () ->
		console.log "Sound: #{@note.sym} #{@dur.time}"

window.cde.Sound = Sound

		
### ===========================================================
# Aggregation (set of notes)
### 
class Aggr

	@PATTERN = ///
		(.+)	# note label list
		/		# separator
		(.+)	# duration
		///

	constructor: (@word) ->
		@sounds = []
		[list, dur] = @word.match(Aggr.PATTERN)[1..2]
		
		console.log "NEW Aggr:list:#{list}|dur:#{dur}"
			
		labels = list.split ','
		@dur = new cde.Dur( dur)
		
		for label in labels
			@sounds.push( new cde.Sound( new cde.Note(label), dur) )
		
	trace: () ->
		console.log "Aggr: #{@word}: cnt:#{@sounds.length} dur:#{@dur.time}"

window.cde.Aggr = Aggr


			
